package org.ala.tiktools.mybatis.interfaces;

import java.util.Comparator;

/**
 * 排序组件
 * - T 为实体组件
 *
 * @author ala
 * @date 2025-01-13 14:43
 */
public interface IOrderBy<E> extends Comparator<E> {
    /**
     *  默认空值
     */
    public static IOrderBy NULL = new IOrderBy() {
        @Override
        public int compare(Object e1, Object e2) {
            return 0;
        }
    };


    /**
     *  排序两个实体
     *  <p> 在分表查询中，如果结果集来自多个分表，查询又含有排序，需要额外的排序逻辑将多个分表的数据聚合起来
     */
    public int compare(E e1, E e2);


    /**
     *  排序项
     */
    public static class Item {
        protected String column;
        protected String tag;
        protected boolean asc, eq;
        protected Object val;
        protected String negate, affirm;
        protected String extreme;

        public static Item build(String column, boolean isAsc) {
            Item i = new Item();
            i.column = column;
            i.asc = isAsc;
            i.tag = isAsc ? "asc" : "desc";
            i.affirm = isAsc ? ">" : "<";
            i.negate = isAsc ? "<" : ">";
            i.extreme = isAsc ? String.format("max(`%s`) as `extreme_%s`", column, column) : String.format("min(`%s`) as `extreme_%s`", column, column);
            return i;
        }

        public Item copy() {
            return build(column, asc);
        }

        public String getColumn() {
            return column;
        }
        public void setColumn(String column) {
            this.column = column;
        }
        public String getTag() {
            return tag;
        }
        public void setTag(String tag) {
            this.tag = tag;
        }
        public boolean isAsc() {return asc;}
        public void setAsc(boolean asc) {
            this.asc = asc;
            this.tag = asc ? "asc" : "desc";
            this.affirm = asc ? ">" : "<";
            this.negate = asc ? "<" : ">";
            this.extreme = asc ? String.format("max(`%s`) as `extreme_%s`", column, column) : String.format("min(`%s`) as `extreme_%s`", column, column);

        }
        public Item asc(boolean asc) {
            setAsc(asc);
            return this;
        }
        public Item negateAsc() {
            setAsc(!asc);
            return this;
        }

        public Object getVal() {return val;}
        public void setVal(Object val) {
            this.val = val;
        }
        public Item val(Object val) {
            setVal(val);
            return this;
        }

        public String getNegate() {
            return negate;
        }

        public void setNegate(String negate) {
            this.negate = negate;
        }

        public String getExtreme() {
            return extreme;
        }

        public void setExtreme(String extreme) {
            this.extreme = extreme;
        }

        public boolean isEq() {
            return eq;
        }

        public void setEq(boolean eq) {
            this.eq = eq;
            this.affirm = this.negate = "=";
        }

        public Item eq(boolean eq) {
            setEq(eq);
            return this;
        }

        public String getAffirm() {
            return affirm;
        }

        public void setAffirm(String affirm) {
            this.affirm = affirm;
        }
    }
}
